package com.sqtracker.recommender.util;

import java.util.Set;

/**
 * 集合相似度计算工具类
 */
public class SimilarityUtil {

    /**
     * 计算Jaccard相似度
     * Jaccard(A,B) = |A ∩ B| / |A ∪ B|
     * @param set1 集合1
     * @param set2 集合2
     * @return 相似度 (0-1)
     */
    public static <T> double calculateJaccardSimilarity(Set<T> set1, Set<T> set2) {
        if (set1.isEmpty() && set2.isEmpty()) {
            return 1.0;  // 两个空集认为是相似的
        }

        if (set1.isEmpty() || set2.isEmpty()) {
            return 0.0;
        }

        // 计算交集大小
        int intersectionSize = 0;
        for (T item : set1) {
            if (set2.contains(item)) {
                intersectionSize++;
            }
        }

        // 计算并集大小
        int unionSize = set1.size() + set2.size() - intersectionSize;

        return (double) intersectionSize / unionSize;
    }

    /**
     * 计算Dice系数
     * Dice(A,B) = 2 * |A ∩ B| / (|A| + |B|)
     * @param set1 集合1
     * @param set2 集合2
     * @return 相似度 (0-1)
     */
    public static <T> double calculateDiceCoefficient(Set<T> set1, Set<T> set2) {
        if (set1.isEmpty() && set2.isEmpty()) {
            return 1.0;
        }

        if (set1.isEmpty() || set2.isEmpty()) {
            return.0;
        }

        // 计算交集大小
        int intersectionSize = 0;
        for (T item : set1) {
            if (set2.contains(item)) {
                intersectionSize++;
            }
        }

        return 2.0 * intersectionSize / (set1.size() + set2.size());
    }

    /**
     * 计算Overlap系数
     * Overlap(A,B) = |A ∩ B| / min(|A|, |B|)
     * @param set1 集合1
     * @param set2 集合2
     * @return 相似度 (0-1)
     */
    public static <T> double calculateOverlapCoefficient(Set<T> set1, Set<T> set2) {
        if (set1.isEmpty() && set2.isEmpty()) {
            return 1.0;
        }

        if (set1.isEmpty() || set2.isEmpty()) {
            return 0.0;
        }

        // 计算交集大小
        int intersectionSize = 0;
        for (T item : set1) {
            if (set2.contains(item)) {
                intersectionSize++;
            }
        }

        return (double) intersectionSize / Math.min(set1.size(), set2.size());
    }
}